<?
/**
 * Copyright 2009 Joe Dotoff
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * HttpRequest class
 * A HTTP request
 *
 * @package     PDog
 * @subpackage  Http
 * @author      Joe D. <nonultimate@gmail.com>
 * @license     Apache License Version 2.0
 * @version     $Id: HttpRequest.php 33 2009-04-21 01:03:44Z nonultimate $
 */
class HttpRequest
{
    /**
     * HTTP header array
     *
     * @var array
     */
    protected $_headers;
    /**
     * HTTP GET array
     *
     * @var array
     */
    protected $_get;
    /**
     * HTTP POST array
     *
     * @var array
     */
    protected $_post;
    /**
     * Constructor
     */
    public function __construct()
    {
        // Initialize
        $this->_headers = array(
            'ACCEPT'          => '',
            'ACCEPT-LANGUAGE' => '',
            'ACCEPT-CHARSET'  => '',
            'ACCEPT-ENCODING' => '',
            'CONNECTION'      => '',
            'CONTENT-LENGTH'  => 0,
            'CONTENT-TYPE'    => '',
            'HOST'            => '',
            'HTTP-METHOD'     => '',
            'HTTP-VERSION'    => '',
            'LOCAL-ADDR'      => '',
            'LOCATION'        => '',
            'QUERY-STRING'    => '',
            'REFERER'         => '',
            'REMOTE-ADDR'     => '',
            'REQUEST-URI'     => '',
            'SCRIPT-NAME'     => '',
            'USER-AGENT'      => ''
        );
        $this->_get = array();
        $this->_post = array();
    }
    /**
     * Get accept of HTTP headers
     *
     * @return string
     */
    public function getAccept()
    {
        return $this->_headers['ACCEPT'];
    }
    /**
     * Get accept charset of HTTP headers
     *
     * @return string
     */
    public function getAcceptCharset()
    {
        return $this->_headers['ACCEPT-CHARSET'];
    }
    /**
     * Get accept encoding of HTTP headers
     *
     * @return string
     */
    public function getAcceptEncoding()
    {
        return $this->_headers['ACCEPT-ENCODING'];
    }
    /**
     * Get accept language of HTTP headers
     *
     * @return string
     */
    public function getAcceptLanguage()
    {
        return $this->_headers['ACCEPT-LANGUAGE'];
    }
    /**
     * Get content length of HTTP headers
     *
     * @return int
     */
    public function getContentLength()
    {
        return $this->_headers['CONTENT-LENGTH'];
    }
    /**
     * Get content type of HTTP headers
     *
     * @return string
     */
    public function getContentType()
    {
        return $this->_headers['CONTENT-TYPE'];
    }
    /**
     * Get a HTTP header data
     *
     * @param  string  The key string of the header, defined in the headers
     * @return mixed
     */
    public function getHeader($name)
    {
        $name = strtoupper($name);
        if (isset($this->_headers[$name])) {
            return $this->_headers[$name];
        }

        return false;
    }
    /**
     * Get all HTTP headers
     *
     * @return array
     */
    public function getHeaders()
    {
        return $this->_headers;
    }
    /**
     * Get HTTP request handler and parse data
     *
     * @param  resource $sock  Socket connection resource
     * @param  string   $data  The HTTP header data
     * @return void
     */
    public function getHandler($sock, $data)
    {
        if (!is_resource($sock)) {
            throw new Exception('The handler of HttpRequest not created');
        }
        if (1024 === strlen($data) and !preg_match('/(\r?\n){2}/')) {
            $data .= fread($sock, 1024);
        }
        $arr = preg_split('/(\r?\n){2}/', $data, 2);
        if (preg_match('/^(head|get|post|put) ([^ ]+) ([^\r\n]+)/i', $arr[0], $matches)) {
            $this->_headers['HTTP-METHOD']  = strtoupper($matches[1]);
            $this->_headers['REQUEST-URI']  = $matches[2];
            $this->_headers['HTTP-VERSION'] = $matches[3];
            $this->_headers['SCRIPT-NAME']  = preg_replace('/\?.*/i', '', $this->_headers['REQUEST-URI']);
            $this->_headers['QUERY-STRING'] = substr($this->_headers['REQUEST-URI'], strlen($this->_headers['SCRIPT-NAME']));
            $this->_headers['REMOTE-ADDR']  = preg_replace('/:.*/', '', stream_socket_get_name($sock, true));
            $this->_headers['LOCAL-ADDR']   = preg_replace('/:.*/', '', stream_socket_get_name($sock, false));
            if (preg_match('/user-agent: ([^\r\n]+)/i', $arr[0], $matches)) {
                $this->_headers['USER-AGENT'] = $matches[1];
            }
            if (preg_match('/host: ([^\r\n]+)/i', $arr[0], $matches)) {
                $this->_headers['HOST'] = $matches[1];
            }
            if (preg_match('/accept: ([^\r\n]+)/i', $arr[0], $matches)) {
                $this->_headers['ACCEPT'] = $matches[1];
            }
            if (preg_match('/accept-language: ([^\r\n]+)/i', $arr[0], $matches)) {
                $this->_headers['ACCEPT-LANGUAGE'] = $matches[1];
            }
            if (preg_match('/accept-charset: ([^\r\n]+)/i', $arr[0], $matches)) {
                $this->_headers['ACCEPT-CHARSET'] = $matches[1];
            }
            if (preg_match('/accept-encoding: ([^\r\n]+)/i', $arr[0], $matches)) {
                $this->_headers['ACCEPT-ENCODING'] = $matches[1];
            }
            if (preg_match('/connection: ([^\r\n]+)/i', $arr[0], $matches)) {
                $this->_headers['CONNECTION'] = $matches[1];
            }
            if (preg_match('/referer: ([^\r\n]+)/i', $arr[0], $matches)) {
                $this->_headers['REFERER'] = $matches[1];
            }
            if (preg_match('/content-length: ([^\r\n]+)/i', $arr[0], $matches)) {
                $this->_headers['CONTENT-LENGTH'] = $matches[1];
            }
            if (preg_match('/content-type: ([^\r\n]+)/i', $arr[0], $matches)) {
                $this->_headers['CONTENT-TYPE'] = $matches[1];
            }
            parse_str($this->_headers['QUERY-STRING'], $this->_get);
            if ('POST' === $this->_headers['HTTP-METHOD']) {
                $post = $arr[1];
                if (0 === strlen($data) % 1024) {
                    $k = 0;
                    while ($k < $this->_headers['CONTENT-LENGTH']) {
                        $size = 1024;
                        if ($this->_headers['CONTENT-LENGTH'] - $k < 1024) {
                            $size = $this->_headers['CONTENT-LENGTH'] - $k;
                        }
                        $post .= fread($sock, $size);
                        $k += $size;
                    }
                }
                parse_str($post, $this->_post);
            }
        }
    }
    /**
     * Get host of HTTP headers
     *
     * @return string
     */
    public function getHost()
    {
        return $this->_headers['HOST'];
    }
    /**
     * Get local address of the connection
     *
     * @return string
     */
    public function getLocalAddr()
    {
        return $this->_headers['LOCAL-ADDR'];
    }
    /**
     * Get location of HTTP headers
     *
     * @return string
     */
    public function getLocation()
    {
        return $this->_headers['LOCATION'];
    }
    /**
     * Get HTTP method
     *
     * @return string
     */
    public function getMethod()
    {
        return $this->_headers['HTTP-METHOD'];
    }
    /**
     * Get query string
     *
     * @return string
     */
    public function getQueryString()
    {
        return $this->_headers['QUERY-STRING'];
    }
    /**
     * Get browser referer
     *
     * @return string
     */
    public function getReferer()
    {
        return $this->_headers['REFERER'];
    }
    /**
     * Get the remote address of the connection
     *
     * @return string
     */
    public function getRemoteAddr()
    {
        return $this->_headers['REMOTE-ADDR'];
    }
    /**
     * Get request URI
     *
     * @return string
     */
    public function getRequestURI()
    {
        return $this->_headers['REQUEST-URI'];
    }
    /**
     * Get the requested file path
     *
     * @return string
     */
    public function getScriptName()
    {
        return $this->_headers['SCRIPT-NAME'];
    }
    /**
     * Get user agent
     *
     * @return string
     */
    public function getUserAgent()
    {
        return $this->_headers['USER-AGENT'];
    }
    /**
     * Get HTTP version
     *
     * @return string
     */
    public function getVersion()
    {
        return $this->_headers['HTTP-VERSION'];
    }
}
?>